#include "stdafx.h"
#include "UiClass.h"
#include "CompAndCandWnd.h"
#include "StatusClass.h"

BOOL UiClass::Register(HINSTANCE hInstance)
{
	WNDCLASSEX wc;
	
    //
    // register class of UI window.
    //
    wc.cbSize         = sizeof(WNDCLASSEX);
    wc.style          = CS_PYGINPUT | CS_IME;
	wc.lpfnWndProc    = UiClassWndProc;
    wc.cbClsExtra     = 0;
    wc.cbWndExtra     = 2 * sizeof(LONG);
    wc.hInstance      = hInstance;
    wc.hCursor        = LoadCursor( NULL, IDC_ARROW );
    wc.hIcon          = NULL;
    wc.lpszMenuName   = NULL;
    wc.lpszClassName  = UiClassName;
    wc.hbrBackground  = NULL;
    wc.hIconSm        = NULL;
	
    if( !RegisterClassEx( (LPWNDCLASSEX)&wc ) )
        return FALSE;
	return TRUE;
}

void UiClass::UnRegister(HINSTANCE hInstance)
{
	UnregisterClass(UiClassName,hInstance);
}

LONG UiClass::NotifyHandle(HIMC hUICurIMC, HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
	LONG lRet = 0L;
    LPINPUTCONTEXT lpIMC;
    HGLOBAL hUIExtra;
    LPUIEXTRA lpUIExtra;

    if (!(lpIMC = ImmLockIMC(hUICurIMC)))
        return 0L;

    hUIExtra = (HGLOBAL)GetWindowLong(hWnd,IMMGWL_PRIVATE);
    lpUIExtra = (LPUIEXTRA)GlobalLock(hUIExtra);

    switch (wParam)
    {
	case IMN_CLOSESTATUSWINDOW:
		if (IsWindow(lpUIExtra->uiStatus.hWnd)) {
			ShowWindow(lpUIExtra->uiStatus.hWnd,SW_HIDE);
		}
		break;
		
	case IMN_OPENSTATUSWINDOW:
		StatusClass::CreateWnd(hWnd,lpUIExtra);
		break;
		
	case IMN_OPENCANDIDATE:
		break;
		
	case IMN_CHANGECANDIDATE:
		break;
		
	case IMN_CLOSECANDIDATE:
		break;
		
	case IMN_SETCONVERSIONMODE:
		StatusClass::UpdateWnd(lpUIExtra);
		break;
		
	case IMN_SETSENTENCEMODE:
		break;
		
	case IMN_SETOPENSTATUS:
		StatusClass::UpdateWnd(lpUIExtra);
		break;
		
	case IMN_SETCANDIDATEPOS:
		break;
		
	case IMN_SETCOMPOSITIONFONT:
		break;
		
	case IMN_SETCOMPOSITIONWINDOW:
		POINT ptSrc;
		SIZE szOffset;
		HDC hDC;

		ptSrc = lpIMC->cfCompForm.ptCurrentPos;
		ClientToScreen(lpIMC->hWnd, &ptSrc);
		hDC = GetDC(lpIMC->hWnd);
		GetTextExtentPoint(hDC,_T("A"),1,&szOffset);
		ReleaseDC(lpIMC->hWnd,hDC);

		lpUIExtra->uiComp.pt.x = ptSrc.x + szOffset.cx;
		lpUIExtra->uiComp.pt.y = ptSrc.y + szOffset.cy;

	    if (IsWindow(lpUIExtra->uiComp.hWnd))
			InvalidateRect(lpUIExtra->uiComp.hWnd,NULL,FALSE);

		break;
		
	case IMN_GUIDELINE:
		break;
		
	case IMN_SETSTATUSWINDOWPOS:
		break;
		
	case IMN_PRIVATE:
		break;
		
	default:
		break;
    }
    GlobalUnlock(hUIExtra);
    ImmUnlockIMC(hUICurIMC);

    return lRet;
}

LRESULT WINAPI UiClassWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
	HIMC           hUICurIMC;
    LPINPUTCONTEXT lpIMC;
    LPUIEXTRA      lpUIExtra;
    HGLOBAL        hUIExtra;
    LONG           lRet = 0L;
	
    hUICurIMC = (HIMC)GetWindowLong(hWnd,IMMGWL_IMC);	
	
    //
    // Even if there is no current UI. these messages should not be pass to 
    // DefWindowProc().
    //
    if (!hUICurIMC)
    {
        switch (message)
        {
		case WM_IME_STARTCOMPOSITION:
		case WM_IME_ENDCOMPOSITION:
		case WM_IME_COMPOSITION:
		case WM_IME_NOTIFY:
		case WM_IME_CONTROL:
		case WM_IME_COMPOSITIONFULL:
		case WM_IME_SELECT:
		case WM_IME_CHAR:
			return 0L;
		default:
			break;
        }
    }
	
    switch (message)
    {
	case WM_CREATE:
		
		//
		// Allocate UI's extra memory block.
		//
		hUIExtra = GlobalAlloc(GHND,sizeof(UIEXTRA));
		lpUIExtra = (LPUIEXTRA)GlobalLock(hUIExtra);

		lpUIExtra->uiComp.pt.x = -1;
		lpUIExtra->uiComp.pt.y = -1;

		CompAndCandWnd::CreateWnd(hWnd,lpUIExtra);

		GlobalUnlock(hUIExtra);
		SetWindowLong(hWnd,IMMGWL_PRIVATE,(DWORD)hUIExtra);
		break;
		
	case WM_IME_SETCONTEXT:		
		if (wParam)
		{
			
			hUIExtra = (HGLOBAL)GetWindowLong(hWnd,IMMGWL_PRIVATE);
			lpUIExtra = (LPUIEXTRA)GlobalLock(hUIExtra);
			
			if (hUICurIMC)
			{
				//
				// input context was chenged.
				// if there are the child windows, the diplay have to be
				// updated.
				//
				lpIMC = ImmLockIMC(hUICurIMC);
				if (lpIMC)
				{
					CompAndCandWnd::Move(hWnd,lpUIExtra,lpIMC);
				}
				else
				{
					CompAndCandWnd::HideWnd(lpUIExtra);
				}
				ImmUnlockIMC(hUICurIMC);
			}
			else   // it is NULL input context.
			{
				CompAndCandWnd::HideWnd(lpUIExtra);				
			}
			GlobalUnlock(hUIExtra);
		}
		break;
		
	case WM_IME_STARTCOMPOSITION:		
	case WM_IME_COMPOSITION:		
	case WM_IME_ENDCOMPOSITION:		
		//
		// Finish to display the composition string.
		//
		lpIMC = ImmLockIMC(hUICurIMC);
		hUIExtra = (HGLOBAL)GetWindowLong(hWnd,IMMGWL_PRIVATE);
		lpUIExtra = (LPUIEXTRA)GlobalLock(hUIExtra);
		CompAndCandWnd::Move(hWnd,lpUIExtra,lpIMC);
		GlobalUnlock(hUIExtra);
		ImmUnlockIMC(hUICurIMC);
		break;
		
	case WM_IME_COMPOSITIONFULL:
		break;
		
	case WM_IME_SELECT:
		break;
		
	case WM_IME_CONTROL:
		break;
		
		
	case WM_IME_NOTIFY:
		lRet = UiClass::NotifyHandle(hUICurIMC, hWnd,message,wParam,lParam);
		break;
		
	case WM_DESTROY:
		
		hUIExtra = (HGLOBAL)GetWindowLong(hWnd,IMMGWL_PRIVATE);
		lpUIExtra = (LPUIEXTRA)GlobalLock(hUIExtra);
		
		if (IsWindow(lpUIExtra->uiStatus.hWnd))
			DestroyWindow(lpUIExtra->uiStatus.hWnd);
		
		if (IsWindow(lpUIExtra->uiCand.hWnd))
			DestroyWindow(lpUIExtra->uiCand.hWnd);
		
		if (IsWindow(lpUIExtra->uiComp.hWnd))
			DestroyWindow(lpUIExtra->uiComp.hWnd);
		
		GlobalUnlock(hUIExtra);
		GlobalFree(hUIExtra);
		break;

	case WM_UI_COMPMOVE:
		hUIExtra = (HGLOBAL)GetWindowLong(hWnd,IMMGWL_PRIVATE);
		lpUIExtra = (LPUIEXTRA)GlobalLock(hUIExtra);
		lpUIExtra->uiComp.pt.x = (long)LOWORD(lParam);
		lpUIExtra->uiComp.pt.y = (long)HIWORD(lParam);
		GlobalUnlock(hUIExtra);
		break;

	default:
		return DefWindowProc(hWnd,message,wParam,lParam);
    }
    return lRet;
}